/*
 * Copyright (c) 2024. hallele, Inc All rights reserved.
 */

package cn.hallele.ms.starter.web.framework.flow;

import cn.hallele.infrastructure.metadata.constant.MsgCodeConst;
import cn.hallele.infrastructure.metadata.exception.children.ActionException;
import cn.hallele.infrastructure.metadata.io.Equipment;
import cn.hallele.infrastructure.metadata.io.Request;
import cn.hallele.infrastructure.metadata.io.User;
import cn.hallele.infrastructure.util.NetUtil;
import cn.hallele.infrastructure.util.ObjectUtil;
import cn.hallele.ms.starter.web.framework.bo.ActionOrder;
import cn.hallele.ms.starter.web.framework.context.ActionContext;
import cn.hallele.ms.starter.web.framework.node.ServiceFlow;
import cn.hallele.ms.starter.web.framework.service.ActionInitializeService;
import cn.hallele.ms.starter.web.framework.service.ActionService;
import com.yomahub.liteflow.annotation.LiteflowComponent;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.web.ServerProperties;

import java.net.InetAddress;
import java.util.Map;

/**
 * hallele_mc_core
 *
 * @author anle5
 * @since 2024/12/23 23:33
 */
@Slf4j
@LiteflowComponent
public class ContextInitializeFlow extends ServiceFlow {
    /**
     * 需要网关/微服务统一接入层实现一个，去调用用户中心查询解析实体
     */
    @Autowired(required = false)
    private ActionInitializeService actionInitializeService;

    @Autowired(required = false)
    private ServerProperties serverProperties;

    /**
     * 执行业务逻辑
     *
     * @throws Exception 业务异常
     */
    @Override
    public void process() throws Exception {
        log.debug("Context initialize flow");
        ActionContext context = this.getContextBean(ActionContext.class);
        if (context.getRequest() == null) {
            context.setRequest(Request.builder().build());
        }
        initializeInitiator(context);
        initializeActionOrder(context);
        initializeClientEquipmentInfo(context);
        initializeServerEquipmentInfo(context);
    }

    /**
     * 初始化订单
     *
     * @param context 上下文
     */
    private void initializeActionOrder(ActionContext context) {
        log.debug("ActionOrder initialize");

        ActionService actionService = context.getActionService();
        if (actionService.needCreateOrder()) {
            ActionOrder actionOrder = actionInitializeService.createActionOrder(context);
            context.setOrder(actionOrder);
        }
    }

    /**
     * 初始化客户端
     *
     * @param context 上下文
     */
    private void initializeClientEquipmentInfo(ActionContext context) {
        log.debug("Client initialize");

        if (context.getClient() == null) {
            Equipment client = new Equipment();
            Map<String, String> clientInfo = NetUtil.getClientInfo();
            HttpServletRequest request = NetUtil.getHttpServletRequest();
            String clientID = NetUtil.getClientID();
            if (ObjectUtil.isBlank(clientID)) {
                log.error("clientID is blank");
                throw new ActionException(MsgCodeConst.CONTEXT_INITIALIZE_FAILED, "ClientID is blank");
            }

            client.setId(clientID);
            client.setIp(clientInfo.get(NetUtil.IP));
            client.setPort(request.getRemotePort());
            client.setHost(request.getRemoteHost());
            client.setInfo(NetUtil.getClientStringInfo());
            client.setType(clientInfo.get(NetUtil.OS_NAME));
            client.setVersion(clientInfo.get(NetUtil.OS_VERSION));
            context.setClient(client);
        }
    }

    /**
     * 初始化服务端
     *
     * @param context 上下文
     */
    private void initializeServerEquipmentInfo(ActionContext context) {
        log.debug("Server initialize");

        if (context.getServer() == null) {
            Equipment server = new Equipment();
            Map<String, String> serverInfo = NetUtil.getServerInfo();
            server.setId(NetUtil.getServerID());
            InetAddress localHost = NetUtil.getLocalHost();
            server.setIp(ObjectUtil.map(localHost, InetAddress::getHostAddress));
            server.setPort(serverProperties.getPort());
            server.setHost(ObjectUtil.map(localHost, InetAddress::getHostName));
            server.setType(serverInfo.get(NetUtil.OS_NAME));
            server.setVersion(serverInfo.get(NetUtil.OS_VERSION));
            server.setInfo(server.getType() + " " + server.getVersion());
            context.setServer(server);
        }
    }

    /**
     * 初始化发起方
     *
     * @param context 上下文
     */
    private void initializeInitiator(ActionContext context) {
        log.debug("Initiator initialize");

        ActionService actionService = context.getActionService();
        if (!actionService.needLogin()) {
            log.debug("No need login, so do not have initiator");
            return;
        }

        User user = actionInitializeService.getUserInfo();
        if (user == null) {
            user = context.getRequest().getInitiator();
        }

        if (user == null) {
            log.error("Initiator UserInfo error,user is null.");
            throw new ActionException(MsgCodeConst.CONTEXT_INITIALIZE_FAILED, "Initiator initialize failed");
        }
        context.getRequest().setInitiator(user);
    }
}
